package com.zenithmind.article.controller;

import com.zenithmind.common.annotation.Log;
import com.zenithmind.common.constant.OperationTypeEnum;
import com.zenithmind.article.pojo.domain.Article;
import com.zenithmind.article.pojo.domain.ArticleLike;
import com.zenithmind.article.pojo.dto.ArticleTagDTO;
import com.zenithmind.article.pojo.dto.StatusUpdateRequest;
import com.zenithmind.article.pojo.query.ArticleQuery;
import com.zenithmind.article.pojo.vo.ArticleVO;
import com.zenithmind.article.pojo.vo.AuthorVO;
import com.zenithmind.article.service.ArticleLikeService;
import com.zenithmind.article.service.ArticleService;
import com.zenithmind.article.service.ArticleFileService;
import com.zenithmind.article.service.ArticleQueryService;
import com.zenithmind.article.service.ArticleTagAssociationService;
import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.util.List;
import java.util.ArrayList;

/**
 * 文章控制器
 * 遵循单一职责原则：专注于文章基础操作
 * 遵循依赖倒置原则：通过构造器注入依赖
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/article")
@Tag(name = "文章管理")
public class ArticleController {

    private final ArticleService articleService;
    private final ArticleLikeService articleLikeService;
    private final ArticleFileService articleFileService;
    private final ArticleQueryService articleQueryService;
    private final ArticleTagAssociationService articleTagAssociationService;

    // 构造器注入，遵循依赖倒置原则
    public ArticleController(
            ArticleService articleService,
            ArticleLikeService articleLikeService,
            ArticleFileService articleFileService,
            ArticleQueryService articleQueryService,
            ArticleTagAssociationService articleTagAssociationService) {
        this.articleService = articleService;
        this.articleLikeService = articleLikeService;
        this.articleFileService = articleFileService;
        this.articleQueryService = articleQueryService;
        this.articleTagAssociationService = articleTagAssociationService;
    }


    @Log(description = "分页查询文章", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "分页查询文章")
    @GetMapping("/pageArticle")
    public Result<PageResult<ArticleVO>> pageArticle(ArticleQuery articleQuery){
        log.info("分页查询文章：{}", articleQuery);
        PageResult<ArticleVO> page = articleService.pageArticle(articleQuery);
        return Result.success(page);
    }

    @Log(description = "获取热门文章", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取热门文章")
    @GetMapping("/getHotArticles")
    public Result<List<ArticleVO>> getHotArticles() {
        log.info("获取热门文章");
        List<ArticleVO> hotArticles = articleQueryService.getHotArticles();
        return Result.success(hotArticles);
    }

    @Log(description = "获取热门文章(博客页面)", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取博客页面热门文章")
    @GetMapping("/blog/getHotArticles")
    public Result<List<ArticleVO>> getBlogHotArticles(@RequestParam(required = false, defaultValue = "5") Integer limit) {
        log.info("获取博客页面热门文章，数量限制：{}", limit);
        List<ArticleVO> hotArticles = articleQueryService.getBlogHotArticles(limit);
        return Result.success(hotArticles);
    }

    @Log(description = "获取活跃作者", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取活跃作者")
    @GetMapping("/blog/getActiveAuthors")
    public Result<List<AuthorVO>> getActiveAuthors(@RequestParam(required = false, defaultValue = "5") Integer limit) {
        log.info("获取活跃作者，数量限制：{}", limit);
        List<AuthorVO> activeAuthors = articleQueryService.getActiveAuthors(limit);
        return Result.success(activeAuthors);
    }

    @Log(description = "获取文章归档", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取文章归档")
    @GetMapping("/getArticleArchives")
    public Result<List<ArticleVO>> getArticleArchives() {
        log.info("获取文章归档");
        List<ArticleVO> archives = articleQueryService.getArticleArchives();
        return Result.success(archives);
    }

    @Log(description = "添加或修改文章", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "添加文章或修改文章")
    @PostMapping("/addOrUpdateArticle")
    public Result<Article> addOrUpdateArticle(@RequestBody Article article){
        log.info("添加文章或修改文章：{}", article);
        Article articleList = articleService.addOrUpdateArticle(article);
        return Result.success(articleList);
    }

    @Log(description = "根据ID查询文章", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "根据id查询文章")
    @GetMapping("/getArticleById/{id}")
    public Result<ArticleVO> getArticleById(@PathVariable String id){
        log.info("根据id查询文章：{}", id);
        ArticleVO article = articleService.getArticleById(id);
        return Result.success(article);
    }

    @Log(description = "批量删除文章", operationType = OperationTypeEnum.DELETE)
    @Operation(summary = "批量删除文章")
    @DeleteMapping("/deleteArticles")
    public Result<Void> deleteArticles(@RequestBody List<String> articleIds){
        log.info("批量删除文章：{}", articleIds);
        articleService.removeByIds(articleIds);
        return Result.success();
    }

    @Log(description = "上传文章封面", operationType = OperationTypeEnum.UPLOAD)
    @Operation(summary = "上传文章封面")
    @PostMapping("/uploadCover")
    public Result<String> uploadCover(@RequestParam("file") MultipartFile file){
        log.info("上传文章封面：{}", file);
        String coverUrl = articleFileService.uploadCover(file);
        return Result.success(coverUrl);
    }

    @Log(description = "给文章绑定标签", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "给文章绑定标签")
    @PostMapping("/bindTags")
    public Result<ArticleVO> bindTags(@RequestBody ArticleTagDTO articleTagDTO){
        log.info("给文章 {} 绑定标签 {}", articleTagDTO.getArticleId(), articleTagDTO.getTagId());
        ArticleVO articleVO = articleTagAssociationService.bindTags(articleTagDTO);
        return Result.success(articleVO);
    }

    @Log(description = "为文章添加分类", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "为文章添加分类")
    @PostMapping("/addCategory")
    public Result<ArticleVO> addCategory(@RequestParam String articleId,@RequestParam String categoryId){
        log.info("给文章 {} 添加分类 {}", articleId, categoryId);
        ArticleVO articleVO = articleTagAssociationService.addCategory(articleId, categoryId);
        return Result.success(articleVO);
    }

    @Log(description = "获取相关文章", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取相关文章")
    @GetMapping("/getRelatedArticles/{articleId}")
    public Result<List<ArticleVO>> getRelatedArticles(@PathVariable String articleId) {
        log.info("获取文章 {} 的相关文章", articleId);
        // 暂时返回空列表，后续通过 ArticleQueryService 实现
        List<ArticleVO> relatedArticles = new ArrayList<>();
        return Result.success(relatedArticles);
    }

    @Log(description = "获取登录用户的文章数量", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "获取登录用户的文章数量")
    @GetMapping("/getArticleCountByUser")
    public Result<Long> getArticleCountByUser() {
        Long count = articleService.getArticleCountByUserId();
        log.info("获取登录用户的文章数量：{}", count);
        return Result.success(count);
    }

    @Log(description = "统计登录用户的文章浏览量", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "统计登录用户的文章浏览量")
    @GetMapping("/countView")
    public Result<Long> countView() {
        Long count = articleService.countView();
        log.info("统计登录用户的文章浏览量：{}", count);
        return Result.success(count);
    }

    @Log(description = "添加或取消文章的点赞", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "添加或取消文章的点赞")
    @PostMapping("/addOrUpdateArticleLike")
    public Result<Void> addOrUpdateArticleLike(@RequestBody ArticleLike articleLike) {
        articleLikeService.addOrUpdateArticleLike(articleLike);
        return Result.success();
    }

    @Log(description = "查询文章点赞状态", operationType = OperationTypeEnum.QUERY)
    @Operation(summary = "查询文章点赞状态")
    @GetMapping("/getArticleLikeStatus")
    public Result<Boolean> getArticleLikeStatus(@RequestParam("articleId") String articleId, @RequestParam("userId") String userId) {
        ArticleLike articleLike = new ArticleLike();
        articleLike.setArticleAndUser(articleId, userId);
        boolean isLike = articleLikeService.getArticleLikeStatus(articleLike);
        return Result.success(isLike);
    }

    @Log(description = "删除文章", operationType = OperationTypeEnum.DELETE)
    @Operation(summary = "删除文章")
    @DeleteMapping("/deleteArticle/{id}")
    public Result<Void> deleteArticle(@PathVariable String id) {
        log.info("删除文章：{}", id);
        articleService.removeById(id);
        return Result.success();
    }

    @Log(description = "发布文章", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "发布文章")
    @PostMapping("/publish/{id}")
    public Result<Boolean> publishArticle(@PathVariable String id) {
        log.info("发布文章：{}", id);
        Boolean result = articleService.publishArticle(id);
        return Result.success(result);
    }

    @Log(description = "下架文章", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "下架文章")
    @PostMapping("/unpublish/{id}")
    public Result<Boolean> unpublishArticle(@PathVariable String id) {
        log.info("下架文章：{}", id);
        Boolean result = articleService.unpublishArticle(id);
        return Result.success(result);
    }

    @Log(description = "更新文章状态", operationType = OperationTypeEnum.UPDATE)
    @Operation(summary = "更新文章状态")
    @PutMapping("/updateStatus/{id}")
    public Result<Boolean> updateArticleStatus(@PathVariable String id, @RequestBody StatusUpdateRequest request) {
        log.info("更新文章状态：{} -> {}", id, request.getStatus());
        Boolean result = articleService.updateArticleStatus(id, request.getStatus());
        return Result.success(result);
    }
}
